package compiler.scanner.dfa;

import java.util.ArrayList;
import java.util.Map;

/// <summary>
/// Summary description for DFATable.
/// </summary>
public class DFATable
{
    //~ Instance fields --------------------------------------------------------

    private String[] accept = null;
    private int[][]  table = null;

    //~ Constructors -----------------------------------------------------------

    public DFATable(DFAState startState)
    {
        convertToTable(startState);
    }

    //~ Methods ----------------------------------------------------------------

    @Override
    public String toString()
    {
        StringBuilder str = new StringBuilder();

        for (int state = 1; state < table.length; state++)
        {
            str.append("State " + state + ":");

            if (accept[state] != null)
            {
                str.append("[accepts:" + accept[state] + "]");
            }

            for (int Char = 0; Char < table[state].length; Char++)
            {
                if (table[state][Char] != 0)
                {
                    char ch = (char)Char;

                    if (Character.isLetterOrDigit(ch) || ((ch >= 32) && (ch <= 128)))
                    {
                        str.append(ch + ":");
                    }
                    else
                    {
                        str.append(String.format("0x%x:", Char)); /* HEX */
                    }

                    str.append((table[state][Char]) + "|");
                }
            }

            str.append(System.getProperty("line.separator"));
        }

        return str.toString();
    }

    private void convertToTable(DFAState startState)
    {
        ArrayList<DFAState> list = startState.getDfaStates();

        table  = new int[list.size() + 1][256]; // state X char
        accept = new String[list.size() + 1];

        // the state zero is reserved for ERROR
        for (int i = 0; i < list.size(); i++)
        {
            DFAState dfaState = list.get(i);

            if (dfaState.acceptingState)
            {
                accept[i + 1] = dfaState.token;
            }

            for (Map.Entry<Character, DFAState> entry : dfaState.transitions.entrySet())
            {
                // Key = char, Value = state
                table[i + 1][entry.getKey()] = list.indexOf(entry.getValue()) + 1;
            }
        }
    }
}
